package com.dingwen.treasure.minio.service;

import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.messages.Bucket;
import lombok.SneakyThrows;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;

/**
 * 　MinioTemplate
 * 　@author dingwen
 * 　@date 2022/7/4
 */
@Component
public class MinioTemplate {


    /**
     * minioClient
     */
    @Resource
    private MinioClient minioClient;


    /**
     * 创建bucket：
     * TODO  ReentrantLock (多线程调用putObject方法其实还是阻塞单线程的因为此方法)
     *
     * @param bucketName bucket名称
     */
    @SneakyThrows(Throwable.class)
    public synchronized void createBucket(String bucketName) {
        if (!minioClient.bucketExists(bucketName)) {
            minioClient.makeBucket(bucketName);
        }
    }

    /**
     * 获取所有桶信息
     *
     * @return {@link List}<{@link Bucket}>
     */
    @SneakyThrows(Throwable.class)
    public List<Bucket> getBuckets() {
        return minioClient.listBuckets();
    }


    /**
     * 获取指定桶信息
     *
     * @param bucketName bucket名称
     * @return {@link Optional}<{@link Bucket}>
     */
    public Optional<Bucket> getBucketInfo(String bucketName) {
        return getBuckets().stream().filter(bucket -> bucket.name().equals(bucketName)).findFirst();
    }

    /**
     * 获取url最长7天
     *
     * @param bucketName bucket名称
     * @param objectName 对象名称
     * @param expires    到期
     * @return {@link String}
     */
    @SneakyThrows(Throwable.class)
    public String getUrl(String bucketName, String objectName, Integer expires) {
        // 默认最大
        expires = Optional.ofNullable(expires).orElse(604800);
        return minioClient.presignedGetObject(bucketName, objectName, expires);
    }

    /**
     * 获取文件输入流
     *
     * @param bucketName bucket名称
     * @param objectName 对象名称
     * @return {@link InputStream}
     */
    @SneakyThrows(Throwable.class)
    public InputStream getInputStream(String bucketName, String objectName) {
        return minioClient.getObject(bucketName, objectName);
    }

    /**
     * 获取文件信息
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     */
    @SneakyThrows(Throwable.class)
    public ObjectStat getObjectInfo(String bucketName, String objectName) {
        return minioClient.statObject(bucketName, objectName);
    }


    /**
     * 存储对象：
     * TODO 分片、大小策略
     *
     * @param bucketName  bucket名称
     * @param objectName  对象名称
     * @param inputStream 输入流
     * @param size        大小
     */
    @SneakyThrows(Throwable.class)
    public void createBucketAndPutObject(String bucketName, String objectName, InputStream inputStream, long size) {
        createBucket(bucketName);
        minioClient.putObject(bucketName, objectName, inputStream, new PutObjectOptions(size, -1));
    }

    /**
     * 存储对象：
     *
     * @param bucketName  bucket名称
     * @param objectName  对象名称
     * @param inputStream 输入流
     * @param size        大小
     */
    @SneakyThrows(Throwable.class)
    public void putObject(String bucketName, String objectName, InputStream inputStream, long size) {
        minioClient.putObject(bucketName, objectName, inputStream, new PutObjectOptions(size, -1));
    }

    /**
     * 删除对象
     *
     * @param bucketName bucket名称
     * @param objectName 对象名称
     */
    @SneakyThrows(Throwable.class)
    public void removeObject(String bucketName, String objectName) {
        minioClient.removeObject(bucketName, objectName);
    }

}
